Ensure LD_LIBRARY_PATH is correct for plugins
authorAlex Crichton <alex@alexcrichton.com>
Thu, 24 Jul 2014 19:30:47 +0000 (12:30 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 24 Jul 2014 19:30:47 +0000 (12:30 -0700)
At runtime rustc will dlopen() plugins, and if plugins have dynamic dependencies
they're likely to be in target/deps, so we need to make sure that directory is
in the right search path.

src/cargo/ops/cargo_rustc/mod.rs
tests/test_cargo_compile_plugins.rs [new file with mode: 0644]
tests/tests.rs

index c4b3199738391545d3298325c0ccc09003f60fd4..605b7c8849eb7fa5cbbe3ee9b64c752d653e6639 100644 (file)
@@ -1,5 +1,7 @@
-use std::io::{fs, UserRWX};
 use std::collections::HashSet;
+use std::dynamic_lib::DynamicLibrary;
+use std::io::{fs, UserRWX};
+use std::os;
 use semver::Version;
 
 use core::{Package, PackageId, PackageSet, Target, Resolve};
@@ -145,7 +147,7 @@ fn compile_custom(pkg: &Package, cmd: &str,
     //       be building a C lib for a plugin
     let layout = cx.layout(false);
     let output = layout.native(pkg);
-    let mut p = process(cmd.next().unwrap(), pkg)
+    let mut p = process(cmd.next().unwrap(), pkg, cx)
                      .env("OUT_DIR", Some(&output))
                      .env("DEPS_DIR", Some(&output))
                      .env("TARGET", cx.config.target());
@@ -204,7 +206,7 @@ fn rustc(package: &Package, target: &Target,
 
 fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
                  cx: &Context, req: PlatformRequirement) -> Vec<ProcessBuilder> {
-    let base = process("rustc", package);
+    let base = process("rustc", package, cx);
     let base = build_base_args(base, target, crate_types.as_slice());
 
     let target_cmd = build_plugin_args(base.clone(), cx, false);
@@ -355,9 +357,16 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
     }
 }
 
-pub fn process<T: ToCStr>(cmd: T, pkg: &Package) -> ProcessBuilder {
+pub fn process<T: ToCStr>(cmd: T, pkg: &Package, cx: &Context) -> ProcessBuilder {
+    // When invoking a tool, we need the *host* deps directory in the dynamic
+    // library search path for plugins and such which have dynamic dependencies.
+    let mut search_path = DynamicLibrary::search_path();
+    search_path.push(cx.layout(false).deps().clone());
+    let search_path = os::join_paths(search_path.as_slice()).unwrap();
+
     util::process(cmd)
         .cwd(pkg.get_root())
+        .env(DynamicLibrary::envvar(), Some(search_path.as_slice()))
         .env("CARGO_PKG_VERSION_MAJOR", Some(pkg.get_version().major.to_string()))
         .env("CARGO_PKG_VERSION_MINOR", Some(pkg.get_version().minor.to_string()))
         .env("CARGO_PKG_VERSION_PATCH", Some(pkg.get_version().patch.to_string()))
diff --git a/tests/test_cargo_compile_plugins.rs b/tests/test_cargo_compile_plugins.rs
new file mode 100644 (file)
index 0000000..98396c8
--- /dev/null
@@ -0,0 +1,73 @@
+use std::os;
+use std::path;
+
+use support::{project, execs, basic_bin_manifest};
+use support::{RUNNING, COMPILING};
+use hamcrest::{assert_that, existing_file};
+use cargo::util::process;
+
+fn setup() {
+}
+
+test!(plugin_to_the_max {
+    let foo = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies.bar]
+            path = "../bar"
+        "#)
+        .file("src/main.rs", r#"
+            #![feature(phase)]
+            #[phase(plugin)] extern crate bar;
+
+            fn main() {}
+        "#);
+    let bar = project("bar")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.0.1"
+            authors = []
+
+            [[lib]]
+            name = "bar"
+            plugin = true
+
+            [dependencies.baz]
+            path = "../baz"
+        "#)
+        .file("src/lib.rs", r#"
+            #![feature(plugin_registrar)]
+
+            extern crate rustc;
+            extern crate baz;
+
+            use rustc::plugin::Registry;
+
+            #[plugin_registrar]
+            pub fn foo(reg: &mut Registry) {
+                println!("{}", baz::baz());
+            }
+        "#);
+    let baz = project("baz")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "baz"
+            version = "0.0.1"
+            authors = []
+
+            [[lib]]
+            name = "baz"
+            crate_type = ["dylib"]
+        "#)
+        .file("src/lib.rs", "pub fn baz() -> int { 1 }");
+    bar.build();
+    baz.build();
+
+    assert_that(foo.cargo_process("cargo-build"),
+                execs().with_status(0));
+})
index 80ca230b8eee77f0931633b633c3bb117e9fd535..a77d451f2ce7b098aa33a338dc6181dc600ac21b 100644 (file)
@@ -30,3 +30,4 @@ mod test_cargo_cross_compile;
 mod test_cargo_run;
 mod test_cargo_version;
 mod test_cargo_new;
+mod test_cargo_compile_plugins;